package insight.web.delegates;

import insight.common.PropertyLoader;
import insight.miescor.annotations.Code;
import insight.miescor.annotations.Constants;
import insight.miescor.annotations.Notebook;
import insight.miescor.annotations.UDF;
import insight.miescor.opp.domain.CodeValue;
import insight.miescor.opp.domain.ICurrency;
import insight.miescor.opp.domain.ILocation;
import insight.miescor.opp.domain.Opportunity;
import insight.miescor.opp.domain.Opportunity.ContractVal;
import insight.miescor.opp.domain.Review;
import insight.miescor.opp.domain.Roles;
import insight.primavera.common.P6helper;
import insight.primavera.common.Utils;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.sormula.Database;
import org.sormula.SormulaException;
import org.sormula.Table;

import com.primavera.ServerException;
import com.primavera.common.value.Cost;
import com.primavera.common.value.EndDate;
import com.primavera.common.value.MultipartObjectIdException;
import com.primavera.common.value.ObjectId;
import com.primavera.integration.client.EnterpriseLoadManager;
import com.primavera.integration.client.GlobalObjectManager;
import com.primavera.integration.client.Session;
import com.primavera.integration.client.bo.BOIterator;
import com.primavera.integration.client.bo.BusinessObjectException;
import com.primavera.integration.client.bo.enm.ProjectStatus;
import com.primavera.integration.client.bo.enm.SummaryLevel;
import com.primavera.integration.client.bo.enm.UDFDataType;
import com.primavera.integration.client.bo.enm.UDFSubjectArea;
import com.primavera.integration.client.bo.object.Currency;
import com.primavera.integration.client.bo.object.EPS;
import com.primavera.integration.client.bo.object.Location;
import com.primavera.integration.client.bo.object.NotebookTopic;
import com.primavera.integration.client.bo.object.OBS;
import com.primavera.integration.client.bo.object.Project;
import com.primavera.integration.client.bo.object.ProjectCode;
import com.primavera.integration.client.bo.object.ProjectCodeAssignment;
import com.primavera.integration.client.bo.object.ProjectCodeType;
import com.primavera.integration.client.bo.object.ProjectNote;
import com.primavera.integration.client.bo.object.ProjectResource;
import com.primavera.integration.client.bo.object.ProjectResourceQuantity;
import com.primavera.integration.client.bo.object.Resource;
import com.primavera.integration.client.bo.object.ResourceAssignment;
import com.primavera.integration.client.bo.object.UDFValue;
import com.primavera.integration.client.bo.object.User;
import com.primavera.integration.client.bo.object.UserOBS;
import com.primavera.integration.network.NetworkException;

public class PrimaveraDelegate {
	public static class ProjectTeam {
		private double units;
		private String resName;
		private String resType;
		private String resId;
		private String roleName;

		public ProjectTeam(ResourceAssignment resAsg)
				throws BusinessObjectException {
			this.units = resAsg.getPlannedUnits().doubleValue();
			this.resName = resAsg.getResourceName();
			this.resId = resAsg.getResourceId();
			this.resType = resAsg.getResourceType().getValue();
			this.roleName = resAsg.getRoleName();
		}

		public ProjectTeam(Resource res, String roleName)
				throws BusinessObjectException {
			this.resName = res.getName();
			this.resId = res.getId();
			this.resType = res.getResourceType().getValue();
			this.roleName = roleName;
		}

		public void append(double units) throws BusinessObjectException {
			this.units += units;
		}

		public String getKey() {
			return roleName != null ? resId + "-" + roleName : resId;
		}

		public double getUnits() {
			return units;
		}

		public void setUnits(double units) {
			this.units = units;
		}

		public String getResName() {
			return resName;
		}

		public void setResName(String resName) {
			this.resName = resName;
		}

		public String getResType() {
			return resType;
		}

		public void setResType(String resType) {
			this.resType = resType;
		}

		public String getResId() {
			return resId;
		}

		public void setResId(String resId) {
			this.resId = resId;
		}

		public String getRoleName() {
			return roleName;
		}

		public void setRoleName(String roleName) {
			this.roleName = roleName;
		}
	}

	private static final String NEW_OPP_EPS = PropertyLoader.getProperty(
			"opportunity.new.epsid", "UR");
	private static final String PROPOSAL_EPS = PropertyLoader.getProperty(
			"opportunity.proposal.epsid", "PRP");
	private static final String ESTIMATION_EPS = PropertyLoader.getProperty(
			"opportunity.estimation.epsid", "EST");
	private static final String ARCHIVED_EPS = PropertyLoader.getProperty(
			"archived.opportunity.epsid", "OARCH");
	private static final String PROPOSAL_OBSName = PropertyLoader.getProperty(
			"opportunity.proposalmanagers.obs", "Proposal Managers");
	private static final String OBS_ESTIMATIONS = "Estimations";
	public static void main(String[] args) {
		try {
			System.setProperty("primavera.bootstrap.home", System.getProperty(
					"primavera.bootstrap.home",
					"D:/OracleApps/Primavera/R83/p6"));
			P6helper helper = new P6helper();
			Session session = helper.getSession();
			Project project = helper.getProjectById("CORP00384");
			System.out.println(project.getName());
			System.out.println(setProjectNotebookContent(session, project,
					"Test", "<p> Test<strong>ing</strong><p>", true, true));
		} catch (Exception ex) {

		}
	}

	public static Map<String, String> getAllUsers(Session session)
			throws BusinessObjectException, ServerException, NetworkException {
		BOIterator<User> userList = session.getEnterpriseLoadManager()
				.loadUsers(new String[] { "Name", "PersonalName" }, null,
						"Name asc");
		Map<String, String> userMap = new HashMap<String, String>();
		while (userList.hasNext()) {
			User user = userList.next();
			userMap.put(user.getName(), user.getPersonalName());
		}
		return userMap;
	}

	public static double conCurrencyVal(Session session, double value,
			String currencyCode) throws BusinessObjectException,
			ServerException, NetworkException {
		ICurrency currency = loadICurrency(session, currencyCode);
		if (currency != null && !currency.isBase()) {
			return currency.convert(value);
		}
		return value;
	}

	public static List<ICurrency> loadCurrencyList(Session session)
			throws BusinessObjectException, ServerException, NetworkException {
		EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
		BOIterator<Currency> currencyItr = elm.loadCurrencies(ICurrency.Fields,
				null, null);
		List<ICurrency> list = new ArrayList<ICurrency>();
		while (currencyItr.hasNext()) {
			list.add(new ICurrency(currencyItr.next()));
		}
		return list;
	}

	public static ICurrency loadICurrency(Session session, String currencyId)
			throws BusinessObjectException, ServerException, NetworkException {
		Currency currency = loadCurrency(session, currencyId);
		return currency != null ? new ICurrency(currency) : null;
	}

	public static Currency loadCurrency(Session session, String currencyId)
			throws BusinessObjectException, ServerException, NetworkException {
		EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
		BOIterator<Currency> currencyItr = elm.loadCurrencies(ICurrency.Fields,
				"Id='" + currencyId + "'", null);

		if (currencyItr.hasNext()) {
			return currencyItr.next();
		}
		return null;
	}

	
	
	public static List<ProjectTeam> loadProjectTeam(Session session,
			Project project) throws BusinessObjectException, ServerException,
			NetworkException {
		HashMap<String, ProjectTeam> mapTeam = new HashMap<String, ProjectTeam>();
		if (project.getSummaryLevel().equals(SummaryLevel.WBSLEVEL)) {
			String[] prjResFields = new String[] { "RoleName" };
			String[] resFields = new String[] { "Name", "Id", "ResourceType" };
			String[] resQtyFileds = new String[] { "Quantity" };

			BOIterator<ProjectResource> resItr = project
					.loadProjectLevelResources(prjResFields, null, null);
			while (resItr.hasNext()) {
				ProjectResource prjRes = resItr.next();
				if(prjRes != null){
					Resource res = prjRes.loadResource(resFields);
					ProjectTeam prjTeam = mapTeam
							.get(prjRes.getRoleName() != null ? res.getId() + "-"
									+ prjRes.getRoleName() : res.getId());
					if (prjTeam == null) {
						prjTeam = new ProjectTeam(res, prjRes.getRoleName());
						mapTeam.put(prjTeam.getKey(), prjTeam);
					}
					BOIterator<ProjectResourceQuantity> resQtyItr = prjRes
							.loadProjectResourceQuantities(resQtyFileds, null, null);
					while (resQtyItr.hasNext()) {
						prjTeam.append(resQtyItr.next().getQuantity().doubleValue());
					}
				}
			}
		} else {
			String[] resAsgFields = new String[] { "ResourceName",
					"ResourceId", "PlannedUnits", "RoleName", "ResourceType" };
			BOIterator<ResourceAssignment> resAsgItr = project
					.loadAllResourceAssignments(resAsgFields, null, null);
			while (resAsgItr.hasNext()) {
				ResourceAssignment resAsg = resAsgItr.next();
				ProjectTeam prjTeam = mapTeam
						.get(resAsg.getRoleName() != null ? resAsg
								.getResourceId() + "-" + resAsg.getRoleName()
								: resAsg.getResourceId());
				if (prjTeam == null) {
					prjTeam = new ProjectTeam(resAsg);
					mapTeam.put(prjTeam.getKey(), prjTeam);
				} else {
					prjTeam.append(resAsg.getPlannedUnits().doubleValue());
				}
			}
		}
		return new ArrayList<ProjectTeam>(mapTeam.values());
	}

	public static List<ILocation> loadLocationList(Session session)
			throws BusinessObjectException, ServerException, NetworkException {
		EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
		BOIterator<Location> locationItr = elm.loadLocations(ILocation.Fields,
				null, null);
		List<ILocation> list = new ArrayList<ILocation>();
		while (locationItr.hasNext()) {
			list.add(new ILocation(locationItr.next()));
		}
		Collections.sort(list, new ILocation.ILocationSort());
		return list;
	}

	public static boolean setProjectNotebookContent(Session session,
			ObjectId projectId, String notebook, String content,
			boolean append, boolean extend) {
		try {
			Project project = Project.load(session, new String[] { "Id" },
					projectId);
			if (project != null)
				return setProjectNotebookContent(session, project, notebook,
						content, append, extend);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean setProjectNotebookContent(Session session,
			ObjectId projectId, String notebook, String content) {
		return setProjectNotebookContent(session, projectId, notebook, content,
				false, false);
	}

	public static boolean setProjectNotebookContent(Session session,
			Project project, String notebook, String content) {
		return setProjectNotebookContent(session, project, notebook, content,
				false, false);
	}

	public static boolean setProjectNotebookContent(Session session,
			Project project, String notebook, String content, boolean append,
			boolean extend) {
		try {
			content = (content == null ? "" : content);
			BOIterator<ProjectNote> noteItr = project.loadAllProjectNotes(
					ProjectNote.getAllFields(), "NotebookTopicName='"
							+ notebook + "'", null);
			if (noteItr.hasNext()) {
				ProjectNote pNote = noteItr.next();
				pNote.setNote(append ? pNote.getNote() + "<br>" + content
						: content);
				pNote.update();
				return true;
			} else {
				EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
				BOIterator<NotebookTopic> topicTypeItr = elm
						.loadNotebookTopics(new String[] { "Name",
								"AvailableForProject" }, "Name='" + notebook
								+ "'", null);
				if (topicTypeItr.hasNext()) {
					NotebookTopic topicType = topicTypeItr.next();
					if (topicType.getAvailableForProject()) {
						ObjectId typeId = topicType.getObjectId();
						ProjectNote note = new ProjectNote(session);
						note.setNotebookTopicObjectId(typeId);
						note.setProjectObjectId(project.getObjectId());
						note.setNote(content);
						note.create();
						return true;
					} else if (extend) {
						topicType.setAvailableForProject(true);
						ObjectId typeId = topicType.getObjectId();
						topicType.update();
						ProjectNote note = new ProjectNote(session);
						note.setNotebookTopicObjectId(typeId);
						note.setProjectObjectId(project.getObjectId());
						note.setNote(content);
						note.create();
						return true;
					} else {
						return false;
					}
				} else if (extend) {
					NotebookTopic topicType = new NotebookTopic(session);
					topicType.setName(notebook);
					topicType.setAvailableForProject(true);
					ObjectId typeId = topicType.create();
					ProjectNote note = new ProjectNote(session);
					note.setNotebookTopicObjectId(typeId);
					note.setProjectObjectId(project.getObjectId());
					note.setNote(content);
					note.create();
					return true;
				} else {
					return false;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public static String getProjectNotebookContent(Session session,
			ObjectId projectId, String notebook) {
		try {
			Project project = Project.load(session, new String[] { "Id" },
					projectId);
			if (project != null)
				return getProjectNotebookContent(session, project, notebook);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static String getProjectNotebookContent(Session session,
			Project project, String notebook) {
		try {
			BOIterator<ProjectNote> noteItr = project.loadAllProjectNotes(
					ProjectNote.getAllFields(), "NotebookTopicName='"
							+ notebook + "'", null);
			if (noteItr.hasNext()) {
				return noteItr.next().getNote();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static String getCodeName(Session session, ObjectId objectId) {
		ProjectCode code;
		try {
			code = ProjectCode.load(session, new String[] { "CodeValue" },
					objectId);
			if (code != null) {
				return code.getCodeValue();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void saveOpportunity(Session session,
			Opportunity opportunity, String userName) throws Exception {
		Project project = createProject(session, opportunity);

		PrimaveraDelegate.assignProjectCode(session, project, PropertyLoader
				.getProperty("project.opportunity.projectcategory",
						"Opportunity"));

		saveDataToP6(session, project, opportunity, userName);

		for (ContractVal contractVal : opportunity.getContractVal()) {
			setProjectNotebookContent(session, project,
					Constants.ProjectFields.NOTEBOOK_CONTRACT_VALUE,
					contractVal.getValue() + " " + contractVal.getCurrency()
							+ "</br>", true, true);
		}

		Cost contractValue = computeContractValue(session,
				opportunity.getContractVal());

		ObjectId projObjId = project.getObjectId();

		setUDFValueCost(session, UDFSubjectArea.PROJECT,
				Constants.ProjectFields.UDF_CONTRACT_VALUE, projObjId,
				contractValue);
	}

	private static Cost computeContractValue(Session session,
			List<ContractVal> list) {
		double contractValDbl = 0;
		for (ContractVal valueObj : list) {
			try {
				contractValDbl += loadICurrency(session, valueObj.getCurrency())
						.convert(
								Double.parseDouble(valueObj.getValue().replace(
										",", "")));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return new Cost(contractValDbl);
	}

	public static void setUDFValueCost(Session session,
			UDFSubjectArea subjectArea, String title, ObjectId objectId,
			Cost cost) throws BusinessObjectException, ServerException,
			NetworkException, MultipartObjectIdException {
		ObjectId udfId = Utils.getUDFTypeObjectId(subjectArea,
				UDFDataType.COST, title, session);
		String fields[] = { "CodeValue", "ForeignObjectId", "UDFTypeObjectId",
				"Text" };
		String where = (new StringBuilder("ForeignObjectId=")).append(objectId)
				.append(" and UDFTypeObjectId=")
				.append(udfId.getPrimaryKeyValue()).toString();
		BOIterator<UDFValue> udfVals = session.getEnterpriseLoadManager()
				.loadUDFValues(fields, where, null);
		if (udfVals.hasNext()) {
			UDFValue udfVal = (UDFValue) udfVals.next();
			udfVal.setCost(cost);
			udfVal.update();
		} else {
			UDFValue udfVal = new UDFValue(session);
			udfVal.setForeignObjectId(objectId);
			udfVal.setUDFTypeObjectId(udfId);
			udfVal.setCost(cost);
			udfVal.create();
		}
	}

	public static boolean assignProjectCode(Session session, Project project,
			int codeId) {
		try {

			if (codeId > 0) {

				ProjectCode codeVal = ProjectCode.load(session,
						new String[] { "CodeTypeObjectId" }, new ObjectId(
								codeId));

				BOIterator<ProjectCodeAssignment> asgItr = project
						.loadProjectCodeAssignments(
								new String[] { "ProjectCodeObjectId" },
								"ProjectCodeTypeObjectId="
										+ codeVal.getCodeTypeObjectId(), null);
				if (asgItr.hasNext()) {
					ProjectCodeAssignment assignment = asgItr.next();
					assignment.setProjectCodeObjectId(new ObjectId(codeId));
					assignment.update();
				} else {

					ProjectCodeAssignment assignment = new ProjectCodeAssignment(
							session);
					assignment.setProjectCodeObjectId(new ObjectId(codeId));
					assignment.setProjectObjectId(project.getObjectId());
					assignment.create();
				}
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean assignProjectCode(Session session, Project project,
			String codeValue) {
		try {

			if (codeValue != null && codeValue != "") {
				ObjectId codeTypeObjectId = null;
				ObjectId codeId = null;
				EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
				BOIterator<ProjectCode> codeItr = elm.loadProjectCodes(
						new String[] { "Description", "CodeValue",
								"CodeTypeObjectId" }, "CodeValue='" + codeValue
								+ "'", null);

				if (codeItr.hasNext()) {
					ProjectCode code = codeItr.next();
					codeTypeObjectId = code.getCodeTypeObjectId();
					codeId = code.getObjectId();
				}

				if (codeId == null) {
					return false;
				}

				BOIterator<ProjectCodeAssignment> asgItr = project
						.loadProjectCodeAssignments(
								new String[] { "ProjectCodeObjectId" },
								"ProjectCodeTypeObjectId=" + codeTypeObjectId,
								null);
				if (asgItr.hasNext()) {
					ProjectCodeAssignment assignment = asgItr.next();
					assignment.setProjectCodeObjectId(codeId);
					assignment.update();
				} else {

					ProjectCodeAssignment assignment = new ProjectCodeAssignment(
							session);
					assignment.setProjectCodeObjectId(codeId);
					assignment.setProjectObjectId(project.getObjectId());
					assignment.create();
				}
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	private static Project createProject(Session session,
			Opportunity opportunity) throws Exception {

		Project project = new Project(session);

		ObjectId epsId = getEPSId(session, NEW_OPP_EPS, true);
		if (epsId == null)
			throw new Exception("EPS name " + NEW_OPP_EPS
					+ " can not be created!");

		if (opportunity.getLocation().getId() > 0)
			project.setLocationObjectId(new ObjectId(opportunity.getLocation()
					.getId()));

		project.setParentEPSObjectId(epsId);
		project.setId(opportunity.getId());
		project.setName(opportunity.getTitle());
		ObjectId projObId = project.create();
		opportunity.setProjectId(projObId.toInteger());
		return Project.load(session, new String[] { "Id" }, projObId);
	}

	public static ObjectId getEPSId(Session session, String epsName,
			boolean create) throws BusinessObjectException, ServerException,
			NetworkException {
		GlobalObjectManager gom = session.getGlobalObjectManager();

		BOIterator<EPS> boiEPS = gom.loadEPS(new String[] { "Id" }, "Id='"
				+ epsName + "'", null);
		ObjectId epsId = null;
		if (boiEPS.hasNext()) {
			epsId = boiEPS.next().getObjectId();
		} else {
			if (create == true) {
				EPS eps = new EPS(session);
				eps.setId(NEW_OPP_EPS);
				eps.setName(NEW_OPP_EPS);
				epsId = eps.create();
			}
		}
		return epsId;
	}

	public static String getUserName(Session session, String userId)
			throws BusinessObjectException, ServerException, NetworkException {
		GlobalObjectManager gom = session.getGlobalObjectManager();
		BOIterator<User> itr = gom.loadUsers(new String[] { "PersonalName" },
				"Name='" + userId + "'", null);
		if (itr.hasNext()) {
			return itr.next().getPersonalName();
		}
		return userId;
	}
	
	

	private static String createNoteBookData(String content, String userName) {
		String newData = "<div class='contentblock'>";
		newData += "<div class='userDetail'>********<strong><span class='userId'>{userName}</span>&nbsp;&nbsp;&nbsp;";
		newData += "<span class='timestamp'>{time}</span></strong>****************</div><div class='content'>{data}</div><div>";

		SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy HH:mm:ss");
		if (content != null && !content.isEmpty()) {
			newData = newData.replace("{data}", content);
			newData = newData.replace("{userName}", userName);
			newData = newData.replace("{time}", sdf.format(new Date()));

			return newData;
		} else
			return "";
	}

	public static int getProjectCodeTypeObjectId(Session session,
			String codeType) throws BusinessObjectException, ServerException,
			NetworkException {
		BOIterator<ProjectCodeType> itr = session.getEnterpriseLoadManager()
				.loadProjectCodeTypes(new String[] { "Name" },
						"Name='" + codeType + "'", null);

		if (itr.hasNext()) {
			return itr.next().getObjectId().toInteger();
		}
		return 0;
	}

	public static int getProjectCodeObjectId(Project project, String codeType)
			throws BusinessObjectException, ServerException, NetworkException {

		BOIterator<ProjectCodeAssignment> itr = project
				.loadProjectCodeAssignments(
						new String[] { "ProjectCodeObjectId" },
						"ProjectCodeTypeName='" + codeType + "'", null);
		if (itr.hasNext()) {
			return itr.next().getProjectCodeObjectId().toInteger();
		}
		return 0;
	}

	public static CodeValue getProjectCodeValueAndObjectId(Project project,
			String codeType) throws BusinessObjectException, ServerException,
			NetworkException {

		BOIterator<ProjectCodeAssignment> itr = project
				.loadProjectCodeAssignments(new String[] {
						"ProjectCodeObjectId", "ProjectCodeValue",
						"ProjectCodeDescription" }, "ProjectCodeTypeName='"
						+ codeType + "'", null);
		if (itr.hasNext()) {
			ProjectCodeAssignment codeAss = itr.next();
			CodeValue option = new CodeValue(codeAss.getProjectCodeObjectId()
					.toInteger(), codeAss.getProjectCodeDescription());
			return option;
		}
		return null;
	}

	public static List<String> getUserRoles(String userid, Database database)
			throws SormulaException {
		List<String> userRoles = new ArrayList<String>();
		Table<Roles> roleTbl = database.getTable(Roles.class);
		List<Roles> roleList = roleTbl.selectAllCustom("where userid = ? ",
				userid);
		for (Roles role : roleList) {
			userRoles.add(role.getRole());
		}
		System.out.println(userRoles.toString());
		return userRoles;
	}

	public static void getDataFromP6(Session session, Project project,
			Object object) {
		getCodeValuesFromP6(project, object);
		getNoteBookValuesFromP6(session, project, object);
		getUDFValuesFromP6(session, project, object);
	}

	private static void getCodeValuesFromP6(Project project, Object object) {
		Field[] projectCodes = ReflectionDelegate.getAnnotatedFields(
				object.getClass(), Code.class);

		for (Field code : projectCodes) {

			try {
				code.setAccessible(true);
				String codeName = code.getAnnotation(Code.class).name();

				code.set(object, PrimaveraDelegate
						.getProjectCodeValueAndObjectId(project, codeName));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void getNoteBookValuesFromP6(Session session,
			Project project, Object object) {
		Field[] notebookFields = ReflectionDelegate.getAnnotatedFields(
				object.getClass(), Notebook.class);
		for (Field notebookField : notebookFields) {
			try {
				notebookField.setAccessible(true);
				String notebook = notebookField.getAnnotation(Notebook.class)
						.topicName();
				notebookField.set(object, PrimaveraDelegate
						.getProjectNotebookContent(session, project, notebook));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void getUDFValuesFromP6(Session session, Project project,
			Object object) {
		Field[] udfFields = ReflectionDelegate.getAnnotatedFields(
				object.getClass(), UDF.class);
		for (Field udfField : udfFields) {
			try {
				udfField.setAccessible(true);
				UDF annotation = udfField.getAnnotation(UDF.class);
				String title = annotation.name();
				switch (annotation.dataType()) {
				case Constants.UDFDataType.TEXT:
					udfField.set(object, Utils.getUDFValueText(
							project.getObjectId(), UDFSubjectArea.PROJECT,
							title, session));
					break;
				case Constants.UDFDataType.FINISH_DATE:
					udfField.set(object, Utils.getUDFValueEndDate(
							project.getObjectId(), UDFSubjectArea.PROJECT,
							title, session));
					break;
				case Constants.UDFDataType.COST:
					Cost cost = getUDFValueCost(project.getObjectId(),
							UDFSubjectArea.PROJECT, title, session);
					if (cost != null) {
						if (udfField.getType() == Cost.class) {
							udfField.set(object, cost);
						} else if (udfField.getType() == double.class
								|| udfField.getType() == Double.class) {
							udfField.set(object, cost.doubleValue());
						} else if (udfField.getType() == int.class
								|| udfField.getType() == Integer.class) {
							udfField.set(object, cost.intValue());
						} else if (udfField.getType() == float.class
								|| udfField.getType() == Float.class) {
							udfField.set(object, cost.floatValue());
						} else if (udfField.getType() == long.class
								|| udfField.getType() == Long.class) {
							udfField.set(object, cost.longValue());
						} else if (udfField.getType() == String.class) {
							udfField.set(object, "" + cost.doubleValue());
						}
					}
					break;
				case Constants.UDFDataType.INTEGER:
					udfField.set(object, Utils.getUDFValueEndDate(
							project.getObjectId(), UDFSubjectArea.PROJECT,
							title, session));
					break;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void saveDataToP6(Session session, Project project,
			Object object, String userName) {
		setCodeValuesToP6(session, project, object);
		setNoteBookValuesToP6(session, project, object, userName);
		setUDFValuesToP6(session, project, object);
	}

	private static void setCodeValuesToP6(Session session, Project project,
			Object object) {
		Field[] projectCodeFields = ReflectionDelegate.getAnnotatedFields(
				object.getClass(), Code.class);
		for (Field projectCodeField : projectCodeFields) {
			try {
				projectCodeField.setAccessible(true);
				// System.out.println("Doing : " +projectCodeField);
				Object value = projectCodeField.get(object);
				if (value != null) {
					PrimaveraDelegate.assignProjectCode(session, project,
							((CodeValue) value).getId());
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void setNoteBookValuesToP6(Session session, Project project,
			Object object, String userName) {

		Field[] notebookFields = ReflectionDelegate.getAnnotatedFields(
				object.getClass(), Notebook.class);
		for (Field notebookField : notebookFields) {
			try {
				notebookField.setAccessible(true);
				Object value = notebookField.get(object);
				Notebook annotation = notebookField
						.getAnnotation(Notebook.class);
				if (value != null) {
					if (annotation.append()) {
						PrimaveraDelegate.setProjectNotebookContent(session,
								project, annotation.topicName(),
								createNoteBookData(value.toString(), userName),
								true, true);
					} else {
						PrimaveraDelegate.setProjectNotebookContent(session,
								project, annotation.topicName(),
								value.toString(), false, true);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void setUDFValuesToP6(Session session, Project project,
			Object object) {
		Field[] udfFields = ReflectionDelegate.getAnnotatedFields(
				object.getClass(), UDF.class);
		for (Field udfField : udfFields) {
			try {
				udfField.setAccessible(true);
				Object value = udfField.get(object);
				UDF annotation = udfField.getAnnotation(UDF.class);
				String title = annotation.name();
				if (value != null) {
					switch (annotation.dataType()) {
					case Constants.UDFDataType.TEXT:
						Utils.setUDFValueText(session, UDFSubjectArea.PROJECT,
								title, project.getObjectId(), value.toString());
						break;
					case Constants.UDFDataType.FINISH_DATE:
						udfField.set(object, Utils.getUDFValueEndDate(
								project.getObjectId(), UDFSubjectArea.PROJECT,
								title, session));
						Utils.setUDFValueDate(session, UDFSubjectArea.PROJECT,
								title, project.getObjectId(), new EndDate(
										(Date) value));
						break;
					case Constants.UDFDataType.COST:
						Class<?> type = udfField.getType();
						Cost cost = null;
						if (type == int.class || type == Integer.class) {
							cost = new Cost(udfField.getInt(object));
						} else if (type == double.class || type == Double.class) {
							cost = new Cost(udfField.getDouble(object));
						} else if (type == Long.class || type == long.class) {
							cost = new Cost(udfField.getDouble(object));
						} else if (type == String.class) {
							cost = new Cost(Double.parseDouble(udfField.get(
									object).toString()));
						}
						setUDFValueCost(session, UDFSubjectArea.PROJECT, title,
								project.getObjectId(), cost);
						break;
					case Constants.UDFDataType.INTEGER:
						Utils.setUDFValueInteger(session,
								UDFSubjectArea.PROJECT, title,
								project.getObjectId(), udfField.getInt(object));
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static Cost getUDFValueCost(ObjectId objectId,
			UDFSubjectArea subjectArea, String title, Session session)
			throws BusinessObjectException, ServerException, NetworkException {
		UDFValue value = Utils.getUDFValue(objectId, subjectArea,
				UDFDataType.COST, title, session);
		return value != null ? value.getCost() : null;
	}

	public static void saveReview(Session session, Review review,
			String userName) throws BusinessObjectException, ServerException,
			NetworkException {
		Project project = Project.load(session, new String[] { "Id" },
				new ObjectId(review.getPrjObjId()));
		saveDataToP6(session, project, review, userName);
	}

	public static String getCodeValue(Session session, int codeObjId)
			throws BusinessObjectException, ServerException, NetworkException {
		ProjectCode projectCode = ProjectCode.load(session,
				new String[] { "CodeValue" }, new ObjectId(codeObjId));
		return projectCode == null ? null : projectCode.getCodeValue();
	}

//	public static void createProjectCopy(Session session, int projectObjId,
//			int pmuser) throws Exception {
//		Project project = Project.load(session, new String[] { "Id", "Name" },
//				new ObjectId(projectObjId));
//		createProject(session, project, ESTIMATION_EPS,
//				PropertyLoader.getProperty("project.estimation.nameprefix",
//						"Estimation For - "),
//				project.getId().replace("O", "E"), PropertyLoader.getProperty(
//						"project.estimation.projectcategory", "Estimation"),
//				ProjectStatus.WHAT_IF);
//
//		chageOppToProposal(session, project, PROPOSAL_EPS,
//				PropertyLoader.getProperty("project.proposal.nameprefix",
//						"Proposal For - "), PropertyLoader.getProperty(
//						"project.proposal.projectcategory", "Proposal"));
//
//		project.setOBSObjectId(new ObjectId(pmuser));
//
//	}

	public static Project createProject(Session session, Project project,
			String epsName, String prefix, String prjId,
			String projectCategory, ProjectStatus prjStatus) throws Exception {

		ObjectId epsId = getEPSId(session, epsName, true);
		if (epsId == null)
			throw new Exception("EPS name " + PROPOSAL_EPS
					+ " can not be created!");

		ObjectId newPrjObjId = project.createCopy(epsId, null, null, null);
		Project newProject = Project.load(session,
				new String[] { "Id", "Name" }, newPrjObjId);
		newProject.setName(prefix + project.getName());
		newProject.setId(prjId);
		if (prjStatus != null)
			newProject.setStatus(prjStatus);
		newProject.update();

		PrimaveraDelegate.assignProjectCode(session, newProject,
				projectCategory);
		return newProject;
	}

	public static void setProjectArchived(Session session, int projectObjId)
			throws Exception {
		Project project = Project.load(session, new String[] { "ObjectId" },
				new ObjectId(projectObjId));

		ObjectId epsId = getEPSId(session, ARCHIVED_EPS, true);
		if (epsId == null)
			throw new Exception("EPS name " + ARCHIVED_EPS
					+ " can not be created!");

		project.setParentEPSObjectId(epsId);
		project.update();

		assignProjectCode(session, project, PropertyLoader.getProperty(
				"project.archived.projectcategory", "Rejected Opportunity"));

	}

	public static List<CodeValue> getOBSUser(Session session)
			throws BusinessObjectException, ServerException, NetworkException {
		EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
		BOIterator<UserOBS> userObsItr = elm.loadUserOBS(new String[] {
				"OBSName", "UserName", "OBSObjectId", "UserObjectId" },
				"OBSName='" + PROPOSAL_OBSName + "'", null);
		List<CodeValue> userList = new ArrayList<CodeValue>();
		while (userObsItr.hasNext()) {
			UserOBS userOb = userObsItr.next();
			userList.add(new CodeValue(userOb.getUserObjectId().toInteger(),
					userOb.getUserName()));
		}
		return userList;
	}

	public static void chageOppToProposal(Session session, Project project,
			String epsName, String prefix, String projectCategory)
			throws Exception {
		ObjectId epsId = getEPSId(session, epsName, true);
		if (epsId == null)
			throw new Exception("EPS name " + PROPOSAL_EPS
					+ " can not be created!");
		String prjId = project.getId().replace("O", "P");
		project.setId(prjId);
		project.setName(prefix + project.getName());
		project.setParentEPSObjectId(epsId);
		project.setStatus(ProjectStatus.WHAT_IF);
		project.update();
		PrimaveraDelegate.assignProjectCode(session, project, projectCategory);
	}

	public static void getChildOBS(Session session, OBS obs,
			List<CodeValue> obsList) throws BusinessObjectException,
			ServerException, NetworkException {
		BOIterator<OBS> obsItr = obs.loadOBSChildren(new String[] { "ObjectId",
				"Name" }, null, null);
		while (obsItr.hasNext()) {
			OBS ob = obsItr.next();
			obsList.add(new CodeValue(ob.getObjectId().toInteger(), ob.getName()));
			getChildOBS(session, ob, obsList);
		}
	}

	public static List<CodeValue> getOBSList(Session session)
			throws BusinessObjectException, ServerException, NetworkException {
		EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
		BOIterator<OBS> obsItr = elm.loadOBS(
				new String[] { "ObjectId", "Name" }, "Name='"
						+ PROPOSAL_OBSName + "'", null);
		List<CodeValue> obsList = new ArrayList<CodeValue>();
		while (obsItr.hasNext()) {
			OBS ob = obsItr.next();
			getChildOBS(session, ob, obsList);
		}
		return obsList;
	}
	
	private static ObjectId getOBSObjectId(Session session, String obsName)
			throws BusinessObjectException, ServerException, NetworkException {
		EnterpriseLoadManager elm = session.getEnterpriseLoadManager();
		BOIterator<OBS> obsItr = elm.loadOBS(
				new String[] { "ObjectId", "Name" }, "Name='" + obsName + "'",
				null);
		while (obsItr.hasNext()) {
			return obsItr.next().getObjectId();
		}
		return null;
	}
	
	public static void createProjectCopy(Session session, int projectObjId,
			int pmuser) throws Exception {
		Project project = Project.load(session, new String[] { "Id", "Name" },
				new ObjectId(projectObjId));
		Project newPrj = createProject(session, project, ESTIMATION_EPS,
				PropertyLoader.getProperty("project.estimation.nameprefix",
						"Estimation For - "),
				project.getId().replace("O", "E"), PropertyLoader.getProperty(
						"project.estimation.projectcategory", "Estimation"),
				ProjectStatus.WHAT_IF);
		ObjectId obsId = null;
		try {
			obsId = getOBSObjectId(session, OBS_ESTIMATIONS);
			System.out.println("obsid "+obsId);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
		if (obsId != null){
			System.out.println("setobsid on :"+newPrj.getObjectId());
			newPrj.setOBSObjectId(obsId);
			newPrj.update();
		}
		chageOppToProposal(session, project, PROPOSAL_EPS,
				PropertyLoader.getProperty("project.proposal.nameprefix",
						"Proposal For - "), PropertyLoader.getProperty(
						"project.proposal.projectcategory", "Proposal"));

		project.setOBSObjectId(new ObjectId(pmuser));
		project.update();
	}
	
	public static void setProjectAsActive(Session session, int projectObjId)
			throws BusinessObjectException, ServerException, NetworkException {
		Project project = Project.load(session, null,
				new ObjectId(projectObjId));
		project.setStatus(ProjectStatus.ACTIVE);
		project.update();

	}
}
